/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.core
{
	import flash.events.Event;
	import flash.utils.Dictionary;
	
	/**
	 * Adaptor for ChainLink that allows proxying handler functions for tracking and automation. 
	 * Requires a unique id mapped to proxied function so it can be identified and invoked remotely.
	 */	
	public class HandlerObserver implements IChainLink
	{
		private var chainLink:IChainLink;
		private var ids:Dictionary;
		
		/**
		 * This class requires a link to the automation tree, pass the client's node here. 
		 * 
		 * @param chainLink  The entry point in the chain for bubbling and receiving automation events. 
		 */
		public function HandlerObserver(chainLink:IChainLink)
		{
			this.chainLink = chainLink;
			ids = new Dictionary();
		}
		
		public function get id():String
		{
			return chainLink.id;
		}
		
		public function addChildLink(childChainLink:IChainLink):void
		{
			chainLink.addChildLink(childChainLink);
		}
		
		public function removeChildLink(childChainLink:IChainLink):void
		{
			chainLink.removeChildLink(childChainLink);
		}
		
		public function addParentLink(parentChainLink:IChainLink):void
		{
			chainLink.addParentLink(parentChainLink);
		}
		
		public function removeParentLink(parentChainLink:IChainLink):void
		{
			chainLink.removeParentLink(parentChainLink);
		}
		
		public function sendUpChain(param:*):void
		{
			chainLink.sendUpChain(param);
		}
		
		/**
		 * Check if the proposition is a handler id, invoke and pass event if so, pass down chain if not. 
		 */
		public function sendDownChain(path:*):String
		{
			var transport:Transport = Transport(path);
			
			if(ids.hasOwnProperty(transport.proposition))
			{
				return ids[transport.proposition](transport.message);
			}
			return chainLink.sendDownChain(path);
		}
		
		/**
		 * Use this function in a controller when attaching listeners to components in a 
		 * view. 
		 * 
		 * @param id       The handler id for tracking/automation.
		 * @param handler  The event handler for this event
		 * @return         A function that splices automation support between the 
		 * event and the handler
		 */
		public function proxy(id:String, handler:Function):Function
		{
			if(ids[id] == null)
			{
				ids[id] = function(event:Event):void
				{
					chainLink.sendUpChain(new Transport(event, id)); /* Bubble events up */
					handler(event);                                  /* Invoke handler */
				}
			}
			return ids[id];
		}
		
		/**
		 * Delete the reference to the proxy function and return the reference so it can be removed 
		 * from any dispatcher.
		 * 
		 * @param handler  The event handler for this event
		 * @return         A function that splices automation support between the
		 * event and the handler
		 */
		public function deleteProxy(id:String):Function
		{
			if(!ids.hasOwnProperty(id))
			{
				return null
			}
			var func:Function = ids[id];
			delete ids[id];
			return func;
		}

	}
}